package model

import (
	"fmt"
	"github.com/sirupsen/logrus"
)

type (
	Project struct {
		Model
		Name        string     `json:"name" gorm:"column:name;size:255;not null;default:'';"`
		ManagerName string     `json:"manager_name" gorm:"column:manager_name;size:255;not null;default:'';"`
		Other       string     `json:"other" gorm:"column:other;size:255;default:'';"`
		Sections    []*Section `json:"sections" gorm:"foreignkey:ProjectID;association_foreignkey:ID"`
	}
)

func GetProjects(index, size int) ([]*Project, int, error) {
	// TODO: Improve the logging
	projects := make([]*Project, 0)
	total := 0
	if err := db.Model(&Project{}).Count(&total).Error; err != nil {
		return nil, -1, err
	}

	if err := db.Model(&Project{}).Offset((index - 1) * size).Limit(size).Find(&projects).Error; err != nil {
		return nil, -1, err
	}

	for _, project := range projects {
		if err := db.Model(project).Related(&project.Sections).Error; err != nil {
			logrus.Error("查找项目[ID: %d]关联小区失败[错误原因: %s]", project.ID, err)
		}
	}

	return projects, total, nil
}

func GetProject(id int) (*Project, error) {
	project := new(Project)
	project.ID = uint(id)
	if err := db.First(project).Error; err != nil {
		logrus.Errorf("查找项目[ID: %d]失败[错误原因: %s]", id, err)
		return nil, fmt.Errorf("查询ID为%d的项目失败", id)
	}
	if err := db.Model(project).Related(&project.Sections).Error; err != nil {
		logrus.Error("查找项目[ID: %d]关联小区失败[错误原因: %s]", id, err)
		return nil, fmt.Errorf("查询ID为%d的项目关联小区失败", id)
	}
	return project, nil
}

func AddProject(project *Project) error {
	// TODO: Improve the logging
	// 将项目信息落库
	if err := db.Create(project).Error; err != nil {
		return fmt.Errorf("添加项目失败，数据回滚失败")
	}

	return nil
}

func UpdateProject(id int, change *Project) error {
	// TODO: Improve the logging
	tx := db.Begin()
	defer tx.Commit()

	project, err := GetProject(id)
	if err != nil {
		return err
	}

	sections := make([]Section, 0)
	if err = tx.Where("project_id = ?", id).Find(&sections).Error; err != nil {
		goto RollBack
	}
	for _, section := range sections {
		if err = tx.Delete(&section).Error; err != nil {
			goto RollBack
		}
	}

	if err := tx.Model(project).Updates(change).Error; err != nil {
		tx.Rollback()
		return err
	}

	return nil

RollBack:
	tx.Rollback()
	return err
}

func (p *Project) Delete() error {
	// TODO: Improve the logging
	var err error

	tx := db.Begin()
	defer tx.Commit()

	sections := make([]Section, 0)
	if err = tx.Where("project_id = ?", p.ID).Find(&sections).Error; err != nil {
		goto RollBack
	}

	for _, section := range sections {
		if err = tx.Delete(&section).Error; err != nil {
			goto RollBack
		}
	}

	if err = tx.Delete(p).Error; err != nil {
		goto RollBack
	}
	return nil
RollBack:
	tx.Rollback()
	return err
}
